# React 插件

import { SourceCode } from '@rspress/core/theme';

<SourceCode href="https://github.com/web-infra-dev/rsbuild/tree/main/packages/plugin-react" />

React 插件提供了对 React 的支持，插件内部集成了 JSX 编译、React Refresh 等功能。

## 快速开始

### 安装插件

你可以通过如下的命令安装插件:

import { PackageManagerTabs } from '@theme';

<PackageManagerTabs command="add @rsbuild/plugin-react -D" />

### 注册插件

你可以在 `rsbuild.config.ts` 文件中注册插件：

```ts title="rsbuild.config.ts"
import { pluginReact } from '@rsbuild/plugin-react';

export default {
  plugins: [pluginReact()],
};
```

注册插件后，你可以直接进行 React 开发。

## 选项

### swcReactOptions

用于配置 SWC 转换 React 代码的行为，等价于 SWC 的 [jsc.transform.react](https://swc.rs/docs/configuration/compilation#jsctransformreact) 选项。

- **类型：**

```ts
interface ReactConfig {
  pragma?: string;
  pragmaFrag?: string;
  throwIfNamespace?: boolean;
  development?: boolean;
  refresh?:
    | boolean
    | {
        refreshReg?: string;
        refreshSig?: string;
        emitFullSignatures?: boolean;
      };
  runtime?: 'automatic' | 'classic' | 'preserve';
  importSource?: string;
}
```

- **默认值：**

```ts
const isDev = process.env.NODE_ENV === 'development';
const defaultOptions = {
  development: isDev,
  refresh: isDev,
  runtime: 'automatic',
};
```

### swcReactOptions.runtime

设置在转换 JSX 时使用哪种运行时。

- **类型：** `'automatic' | 'classic' | 'preserve'`
- **默认值：** `'automatic'`

#### automatic

默认情况下，Rsbuild 使用 `runtime: 'automatic'` 来利用 React 17 中引入的 [新版 JSX 转换](https://legacy.reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html)。

采用这种方式时，无需在每个 JSX 文件中手动导入 React。

:::tip
React 16.14.0 及更高版本支持新版 JSX 运行时。
:::

#### classic

对于 React 16.14.0 之前的版本，将 `runtime` 设置为 `'classic'`：

```ts
pluginReact({
  swcReactOptions: {
    runtime: 'classic',
  },
});
```

当使用经典 JSX 运行时的时候，你必须在代码中手动导入 React：

```jsx title="App.jsx"
import React from 'react';

function App() {
  return <h1>Hello World</h1>;
}
```

#### preserve

使用 `runtime: 'preserve'` 可以保持 JSX 语法原样，不做任何转换，这在开发需要保留 JSX 代码的库时非常有用。

```ts
pluginReact({
  swcReactOptions: {
    runtime: 'preserve',
  },
});
```

### swcReactOptions.importSource

当 `runtime` 为 `'automatic'` 时，你可以通过 `importSource` 来指定 JSX runtime 的引入路径。

- **类型：** `string`
- **默认值：** `'react'`

比如，在使用 [Emotion](https://emotion.sh/) 时，你可以将 `importSource` 设置为 `'@emotion/react'`：

```ts
pluginReact({
  swcReactOptions: {
    importSource: '@emotion/react',
  },
});
```

> 参考 [自定义 JSX](/guide/framework/react#自定义-jsx) 了解更多。

### swcReactOptions.refresh

- **类型：** `boolean`
- **默认值：** 基于 [fastRefresh](#fastrefresh) 和 [dev.hmr](/config/dev/hmr)

是否启用 [React Fast Refresh](https://npmjs.com/package/react-refresh)。

大多数情况下，你应该使用插件的 [fastRefresh](#fastrefresh) 选项来启用或禁用 Fast Refresh。

### splitChunks

在 [chunkSplit.strategy](/config/performance/chunk-split) 设置为 `split-by-experience` 时，Rsbuild 默认会自动将 `react` 和 `router` 相关的包拆分为单独的 chunk:

- `lib-react.js`：包含 `react`、`react-dom`，以及它们的子依赖（`scheduler`）。
- `lib-router.js`：包含 `react-router`、`react-router-dom`，以及它们的子依赖（`history`，`@remix-run/router`）。

该选项用于控制这一行为，决定是否需要将 `react` 和 `router` 相关的包拆分为单独的 chunk。

- **类型：**

```ts
type SplitChunks =
  | boolean
  | {
      react?: boolean;
      router?: boolean;
    };
```

- **默认值：** `true`（等价于 `{ react: true, router: true }`）

例如，禁用所有 chunks 拆分：

```ts
pluginReact({ splitChunks: false });
```

或是仅禁用 `router` chunk 拆分：

```ts
pluginReact({
  splitChunks: {
    react: true,
    router: false,
  },
});
```

### enableProfiler

- **类型：** `boolean`
- **默认值：** `false`

当设置为 `true` 时，在生产构建中启用 React 性能分析器以用于性能分析。需要搭配 React DevTools 来检查分析结果并识别潜在的性能优化方案。分析会增加一些额外开销，因此出于性能考虑，在生产模式中默认是禁用的。

```ts title="rsbuild.config.ts"
pluginReact({
  // 仅在 REACT_PROFILER 为 true 时启用性能分析器
  // 因为该选项会增加构建时间并产生一些额外开销
  enableProfiler: process.env.REACT_PROFILER === 'true',
});
```

执行构建脚本时，设置 `REACT_PROFILER=true` 即可：

```json title="package.json"
{
  "scripts": {
    "build:profiler": "REACT_PROFILER=true rsbuild build"
  }
}
```

由于 Windows 不支持上述用法，你也可以使用 [cross-env](https://npmjs.com/package/cross-env) 来设置环境变量，这可以确保在不同的操作系统中都能正常使用：

```json title="package.json"
{
  "scripts": {
    "build:profiler": "cross-env REACT_PROFILER=true rsbuild build"
  },
  "devDependencies": {
    "cross-env": "^7.0.0"
  }
}
```

> 关于使用 React DevTools 进行性能分析的详细信息，请参见 [React 文档](https://legacy.reactjs.org/docs/optimizing-performance.html#profiling-components-with-the-devtools-profiler)。

### reactRefreshOptions

- **类型：**

```ts
type ReactRefreshOptions = {
  // @link https://rspack.rs/config/module#condition
  test?: Rspack.RuleSetCondition;
  include?: Rspack.RuleSetCondition;
  exclude?: Rspack.RuleSetCondition;
  library?: string;
  forceEnable?: boolean;
};
```

- **默认值：**

```js
const defaultOptions = {
  test: [/\.(?:js|jsx|mjs|cjs|ts|tsx|mts|cts)$/],
  include: [
    // Same as Rsbuild's `source.include` configuration
  ],
  exclude: [
    // Same as Rsbuild's `source.exclude` configuration
  ],
  resourceQuery: { not: /^\?raw$/ },
};
```

设置 [@rspack/plugin-react-refresh](https://github.com/rspack-contrib/rspack-plugin-react-refresh) 的选项，传入的值会与默认值进行浅合并。

- **示例：**

```js
pluginReact({
  reactRefreshOptions: {
    exclude: [/some-module-to-exclude/, /[\\/]node_modules[\\/]/],
  },
});
```

### fastRefresh

- **类型：** `boolean`
- **默认值：** `true`

是否在开发模式下启用 [React Fast Refresh](https://npmjs.com/package/react-refresh)。

当 `fastRefresh` 设置为 `true` 时，`@rsbuild/plugin-react` 会自动注册 [@rspack/plugin-react-refresh](https://github.com/rspack-contrib/rspack-plugin-react-refresh) 插件。

如果你需要禁用 Fast Refresh，可以将其设置为 `false`：

```ts
pluginReact({
  fastRefresh: false,
});
```
